package com.xinsoft.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.common.exception.BDException;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.dto.InOrOutStock;
import com.xinsoft.entity.dto.ScmStockDTO;
import com.xinsoft.entity.dto.ScmStockParam;
import com.xinsoft.entity.po.ScmStock;
import com.xinsoft.entity.po.ScmStockHis;
import com.xinsoft.service.ScmStockHisService;
import com.xinsoft.service.ScmStockService;
import com.xinsoft.mapper.ScmStockMapper;
import com.xinsoft.service.SysDocumentNumService;
import com.xinsoft.utils.TokenUtil;
import lombok.Synchronized;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author ZYM
 * @description 针对表【scm_stock(库存表)】的数据库操作Service实现
 * @createDate 2023-08-15 15:42:43
 */
@Service
public class ScmStockServiceImpl extends ServiceImpl<ScmStockMapper, ScmStock>
        implements ScmStockService {
    @Autowired
    private ScmStockHisService stockHisService;
    @Autowired
    private SysDocumentNumService sysDocumentNumService;

    @Override
    public IPage<ScmStockDTO> findPageListByParam(ScmStockParam param) {
        // 分页
        Page<ScmStockDTO> page = new Page<ScmStockDTO>(param.getCurrentPage(), param.getPageSize());
        IPage<ScmStockDTO> resultPage = this.baseMapper.findListByParam(page, param);
        // 返回值
        return resultPage;
    }

    /**
     * 分页
     *
     * @param param
     * @return
     */
    @Override
    public List<ScmStockDTO> findListByParam(ScmStockParam param) {
        // 分页
        List<ScmStockDTO> result = this.baseMapper.findListByParam(param);
        // 返回值
        return result;
    }

    /**
     * 合计行
     *
     * @param param
     * @return
     */
    @Override
    public ScmStockDTO findTotalByParam(ScmStockParam param) {

        ScmStockDTO total = this.baseMapper.findTotalByParam(param);
        // 返回值
        return total;
    }

    @Override
    @Synchronized
    public void saveInventoryChange(List<ScmStockHis> stockHisList, List<ScmStock> stockList) {
        stockHisService.saveBatch(stockHisList);
        this.saveOrUpdateBatch(stockList);
    }

    /**
     * 更新库存
     *
     * @param sourceBillType 单据类型
     * @param sourceCode     来源单据编号
     * @param itemList       变动明细列表参数
     * @param changeType     变动类型（0减少，1增加）
     */
    public void updateInventory(Integer sourceBillType, String sourceCode, List<InOrOutStock> itemList, Integer changeType) {
        List<ScmStock> stockList = new ArrayList<>();
        List<ScmStockHis> stockHisList = new ArrayList<>();

        itemList.forEach(item -> {
            ScmStock stock = this.getOne(Wrappers.lambdaQuery(ScmStock.class)
                    .eq(Objects.nonNull(item.getMaterialId()), ScmStock::getMaterialId, item.getMaterialId())
                    .eq(Objects.nonNull(item.getWarehouseId()), ScmStock::getWarehouseId, item.getWarehouseId())
                    .eq(Objects.nonNull(item.getWarehItemId()), ScmStock::getWarehItemId, item.getWarehItemId())
                    .eq(StringUtils.isNotEmpty(item.getBatch()), ScmStock::getBatchNo, item.getBatch()));
            if (Objects.isNull(stock) && changeType.equals(Const.ChangeType.SUBTRACT)) {
                throw new BDException("库存数据不存在");
            }
            ScmStockHis stockHis = new ScmStockHis();
            stockHis.setChangeTime(new Date());
            stockHis.setChangePersonId(TokenUtil.getUserId());
            stockHis.setChangeType(changeType);
            stockHis.setSourceDoc(sourceBillType);
            stockHis.setDocNo(sourceCode);
            stockHis.setBatchNo(item.getBatch());
            stockHis.setWarehouseId(item.getWarehouseId());
            stockHis.setWarehItemId(item.getWarehItemId());
            stockHis.setChangeNum(item.getQty());
            stockHis.setMaterialId(item.getMaterialId());
            // 辅助单位数量 = 主单位数量 * 换算系数
            stockHis.setChangeAssistNum(stockHis.getChangeNum().multiply(item.getConvCoefficient()));
            stockHis.setConvCoefficient(item.getConvCoefficient());
            if (Objects.nonNull(stock)) {    // 存在库存记录，则更新库存相关信息记录
                stockHis.setBeforeNum(stock.getBatchNum());
                if (changeType.equals(Const.ChangeType.ADD)) {
                    stockHis.setAfterNum(stock.getBatchNum().add(item.getQty()));
                    // 批次数量 = 当前批次数量 + 入库数量
                    stock.setBatchNum(stock.getBatchNum().add(item.getQty()));
                    // 可用数量 = 当前可用数量 + 入库数量
                    stock.setBatchNumFree(stock.getBatchNumFree().add(item.getQty()));
                } else {
                    stockHis.setAfterNum(stock.getBatchNum().subtract(item.getQty()));
                    // 批次数量 = 当前批次数量 - 出库数量
                    stock.setBatchNum(stock.getBatchNum().subtract(item.getQty()));
                    // 可用数量 = 当前可用数量 - 出库数量
                    stock.setBatchNumFree(stock.getBatchNumFree().subtract(item.getQty()));
                }
            } else { // 不存在库存记录，则新增库存信息记录
                stockHis.setBeforeNum(BigDecimal.ZERO);
                stockHis.setAfterNum(item.getQty());

                stock = new ScmStock();
                stock.setStockCode(sysDocumentNumService.getSysDocumentNumByDocumentId(Const.DOCUMENT_ID.STOCK_DOCUMENT));
                sysDocumentNumService.incrementLastSerialByDocumentId(Const.DOCUMENT_ID.STOCK_DOCUMENT);
                // 批次数量 = 入库数量
                stock.setBatchNum(item.getQty());
                // 可用数量 = 入库数量
                stock.setBatchNumFree(item.getQty());
            }

            // 辅助单位数量 = 主单位数量 * 换算系数
            stock.setBatchAssistNum(stock.getBatchNum().multiply(item.getConvCoefficient()));
            stock.setWarehouseId(item.getWarehouseId());
            stock.setWarehItemId(item.getWarehItemId());
            stock.setMaterialId(item.getMaterialId());
            // stock.setStockType(Const.StockType.PURCHASE_INSTOCK);
            stock.setBatchNo(item.getBatch());
            stock.setBatchNumFrozen(stock.getBatchNumFrozen() == null ? BigDecimal.ZERO : stock.getBatchNumFrozen());
            stock.setBatchPrice(item.getBatchPrice());
            stock.setConvCoefficient(item.getConvCoefficient());

            stockHisList.add(stockHis);
            stockList.add(stock);
        });
        stockHisService.saveBatch(stockHisList);
        this.saveOrUpdateBatch(stockList);
    }

}




